package com.blustreaksw.cyclecoach.btle;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import android.annotation.SuppressLint;

/***********************************************************************
 * Enum container that hold service and characteristic UUIDs
 * for various types of Bluetooth LE devices.
 * 
 * @author Tomas Rivera
 * 
 ***********************************************************************/
public enum BtleDeviceType {
	/**********************************************************************
	 * Heart rate monitoring device.
	 * @see
	 *  <a href="https://developer.bluetooth.org/gatt/profiles/Pages/ProfileViewer.aspx?u=org.bluetooth.profile.heart_rate.xml">
	 *  org.bluetooth.profile.heart_rate</a>
	 **********************************************************************/
	HEART_RATE_MONITOR(1),
	/**********************************************************************
	 * Cycling power meter device.
	 * @see
	 * 	<a href="https://developer.bluetooth.org/gatt/profiles/Pages/ProfileViewer.aspx?u=org.bluetooth.profile.cycling_power.xml">
	 * 	org.bluetooth.profile.cycling_power</a>
	 **********************************************************************/
	CYCLING_POWER_METER(2),
	/**********************************************************************
	 * Cycling speed and cadence sensor.
	 * @see
	 * 	<a href="https://developer.bluetooth.org/gatt/profiles/Pages/ProfileViewer.aspx?u=org.bluetooth.profile.cycling_speed_and_cadence.xml">
	 * 	org.bluetooth.profile.cycling_speed_and_cadence</a>
	 **********************************************************************/
	CYCLING_SPEED_CADENCE_SENSOR(3),
	/**********************************************************************
	 * Unrecognized/unsupported device.
	 **********************************************************************/
	UNSUPPORTED(4);
	
	private int value;
	
	private BtleDeviceType(int v) {
		this.value = v;
	}
	
	@SuppressLint("UseSparseArrays")
	private static final Map<Integer, BtleDeviceType> intToTypeMap = new HashMap<Integer, BtleDeviceType>();
	static {
		for(BtleDeviceType type : BtleDeviceType.values()) {
			intToTypeMap.put(type.value, type);
		}
	}
	
	/**********************************************************************
	 * Get the numeric value of the enum.
	 * @returns BtleDeviceType numeric value
	 **********************************************************************/
	public int getValue() {
		return this.value;
	}
	
	/**********************************************************************
	 * Get the BtleDeviceType that corresponds to a numeric value.
	 * @returns BtleDeviceType
	 **********************************************************************/
	public static BtleDeviceType fromInt(int i) {
		BtleDeviceType type = intToTypeMap.get(Integer.valueOf(i));
		if(type == null) {
			return BtleDeviceType.UNSUPPORTED;
		}
		
		return type;
	}
	
	
	/*public static BtleDeviceType fromInt(int v) {
		if(v == HEART_RATE_MONITOR.value) {
			return HEART_RATE_MONITOR;
		} else if(v == CYCLING_POWER_METER.value) {
			return CYCLING_POWER_METER;
		} else if(v == CYCLING_SPEED_CADENCE_SENSOR.value) {
			return CYCLING_SPEED_CADENCE_SENSOR;
		} else {
			return UNSUPPORTED;
		}
	}*/
	
	///////////////////////////////////////////////////////////////////////
	// Bluetooth LE Service UUID definitions
	///////////////////////////////////////////////////////////////////////
	final static private UUID SERVICE_HEART_RATE =
			UUID.fromString("0000180d-0000-1000-8000-00805f9b34fb");
	final static private UUID SERVICE_CYCLING_POWER =
			UUID.fromString("00001818-0000-1000-8000-00805f9b34fb");
	final static private UUID SERVICE_CYCLING_SPEED_CADENCE =
			UUID.fromString("00001816-0000-1000-8000-00805f9b34fb");
	
	///////////////////////////////////////////////////////////////////////
	// Bluetooth LE Notifiable Characteristic UUID definitions
	///////////////////////////////////////////////////////////////////////
	final static private UUID CHARACTERISTIC_HEART_RATE_MEASUREMENT =
			UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb");
	final static private UUID CHARACTERISTIC_CYCLING_POWER_MEASUREMENT =
			UUID.fromString("00002a63-0000-1000-8000-00805f9b34fb");
	final static private UUID CHARACTERISTIC_CYCLING_SPEED_CADENCE_MEASUREMENT =
			UUID.fromString("00002a5b-0000-1000-8000-00805f9b34fb");
	
	///////////////////////////////////////////////////////////////////////
	// Bluetooth LE Readable Characteristic UUID definitions
	///////////////////////////////////////////////////////////////////////
	final static private UUID CHARACTERISTIC_BATTERY_LEVEL =
			UUID.fromString("00002a19-0000-1000-8000-00805f9b34fb");
	final static private UUID CHARACTERISTIC_MANUFACTURER_STRING =
			UUID.fromString("00002a29-0000-1000-8000-00805f9b34fb");
	final static private UUID CHARACTERISTIC_MODEL_NUMBER_STRING =
			UUID.fromString("00002a24-0000-1000-8000-00805f9b34fb");
	final static private UUID CHARACTERISTIC_FIRMWARE_REVISION_STRING =
			UUID.fromString("00002a26-0000-1000-8000-00805f9b34fb");
	final static private UUID CHARACTERISTIC_APPEARANCE =
			UUID.fromString("00002a01-0000-1000-8000-00805f9b34fb");
	final static private UUID CHARACTERISTIC_BODY_SENSOR_LOCATION =
			UUID.fromString("00002a38-0000-1000-8000-00805f9b34fb");
	
	///////////////////////////////////////////////////////////////////////
	// Bluetooth LE Descriptor UUID definitions
	///////////////////////////////////////////////////////////////////////
	final static private UUID DESCRIPTOR_CHAR_CLIENT_CONFIG =
			UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");

	/**************************************************************
	 * Returns a string that defines the purpose of the device.
	 * @return String
	 **************************************************************/
	@Override
	public String toString() {
		switch(this) {
		case HEART_RATE_MONITOR:
			return new String("Heart Rate Monitor");
		case CYCLING_POWER_METER:
			return new String("Cycling Power");
		case CYCLING_SPEED_CADENCE_SENSOR:
			return new String("Cycling Speed and Cadence Sensor");
		case UNSUPPORTED:
			return new String("Unsupported Device");
		}
		
		return new String("Unsupported Device");
	}
	
	/**************************************************************
	 * Returns device type that matches the string passed.
	 * @return BtleDeviceType
	 **************************************************************/
	public static BtleDeviceType stringToDeviceType(String s) {
		if(s.equals(HEART_RATE_MONITOR.toString())) {
			return HEART_RATE_MONITOR;
		} else if(s.equals(CYCLING_POWER_METER.toString())) {
			return CYCLING_POWER_METER;
		} else if(s.equals(CYCLING_SPEED_CADENCE_SENSOR.toString())) {
			return CYCLING_SPEED_CADENCE_SENSOR;
		} else {
			return UNSUPPORTED;
		}
	}
	
	/**************************************************************
	 * Returns service UUID for the device type.
	 * @return UUID
	 **************************************************************/
	public UUID serviceUUID() {
		switch(this) {
		case HEART_RATE_MONITOR:
			return SERVICE_HEART_RATE;
		case CYCLING_POWER_METER:
			return SERVICE_CYCLING_POWER;
		case CYCLING_SPEED_CADENCE_SENSOR:
			return SERVICE_CYCLING_SPEED_CADENCE;
		case UNSUPPORTED:
			return null;
		}
		
		return null;
	}
	
	/**************************************************************
	 * Returns characteristic UUID for the device type.
	 * @return UUID
	 **************************************************************/
	public UUID notifiableCharacteristicUUID() {
		switch(this) {
		case HEART_RATE_MONITOR:
			return CHARACTERISTIC_HEART_RATE_MEASUREMENT;
		case CYCLING_POWER_METER:
			return CHARACTERISTIC_CYCLING_POWER_MEASUREMENT;
		case CYCLING_SPEED_CADENCE_SENSOR:
			return CHARACTERISTIC_CYCLING_SPEED_CADENCE_MEASUREMENT;
		case UNSUPPORTED:
			return null;
		}
		
		return null;
	}
	
	/**************************************************************
	 * Get battery level characteristic UUID.
	 * @return UUID
	 **************************************************************/	
	public static UUID batteryLevelCharacteristicUUID() {
		return CHARACTERISTIC_BATTERY_LEVEL;
	}
	
	/**************************************************************
	 * Get firmware revision characteristic UUID.
	 * @return UUID
	 **************************************************************/	
	public static UUID firmwareRevisionCharacteristicUUID() {
		return CHARACTERISTIC_FIRMWARE_REVISION_STRING;
	}
	
	/**************************************************************
	 * Get appearance characteristic UUID.
	 * @return UUID
	 **************************************************************/	
	public static UUID appearanceCharacteristicUUID() {
		return CHARACTERISTIC_APPEARANCE;
	}
	
	/**************************************************************
	 * Get sensor location characteristic UUID.
	 * @return UUID
	 **************************************************************/	
	public static UUID sensorLocationCharacteristicUUID() {
		return CHARACTERISTIC_BODY_SENSOR_LOCATION;
	}
	
	/**************************************************************
	 * Get client configuration descriptor characteristic UUID.
	 * @return UUID
	 **************************************************************/	
	public static UUID getCharClientConfigDescriptor() {
		return DESCRIPTOR_CHAR_CLIENT_CONFIG;
	}
	
	/**************************************************************
	 * Get manufacturer name characteristic UUID.
	 * @return UUID
	 **************************************************************/	
	public static UUID manufacturerCharacteristicUUID() {
		return CHARACTERISTIC_MANUFACTURER_STRING;
	}
	
	/**************************************************************
	 * Get model number characteristic UUID.
	 * @return UUID
	 **************************************************************/	
	public static UUID modelNumberCharacteristicUUID() {
		return CHARACTERISTIC_MODEL_NUMBER_STRING;
	}
	
	
}
